package cn.com.nes.site.modules.sale;

import cn.com.nes.common.exception.BusinessException;
import cn.com.nes.mybatis.agent.crm.entity.Opportunity;
import cn.com.nes.mybatis.agent.ope.entity.SaleOrderInfo;
import cn.com.nes.site.entity.em.crm.saleorder.SaleOrderStatusEnum;
import cn.com.nes.site.modules.opportuntiy.OpportunityBusiness;
import cn.com.nes.site.modules.sale.bo.SaleBO;
import cn.com.nes.site.modules.sale.bo.SaleDetailBO;
import cn.com.nes.site.modules.sale.dto.SaleDetailDTO;
import cn.com.nes.site.modules.sale.enums.SaleTypeEnum;
import cn.com.nes.site.service.crm.clue.CrmClueService;
import cn.com.nes.site.service.crm.clue.bo.ClueBO;
import cn.com.nes.site.service.crm.customer.CrmCustomerService;
import cn.com.nes.site.service.crm.customer.bo.CustomerBO;
import cn.com.nes.site.service.crm.customer.dto.CustomerDTO;
import cn.com.nes.site.service.crm.customer.dto.CustomerDetailDTO;
import cn.com.nes.site.service.crm.opportunity.bo.GetOpportunityDetailBO;
import cn.com.nes.site.service.crm.opportunity.bo.OpportunityBO;
import cn.com.nes.site.service.crm.opportunity.dto.OpportunityDetailDTO;
import cn.com.nes.site.service.crm.order.SaleOrderInfoService;
import cn.com.nes.site.service.crm.order.bo.SaleOrderBO;
import cn.com.nes.site.service.crm.order.dto.SaleOrderDetailDTO;
import cn.com.nes.site.service.product.GGoodsService;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Optional;

@Data
@Slf4j
public abstract class SaleHandle {

    @Resource
    protected CrmClueService crmClueService;

    @Resource
    protected CrmCustomerService crmCustomerService;

    @Resource
    protected SaleOrderInfoService saleOrderInfoService;

    @Resource
    protected OpportunityBusiness opportunityBusiness;

    @Resource
    protected GGoodsService gGoodsService;

    public abstract SaleTypeEnum getSaleTypeEnum();

    public void handleSaleSave(SaleBO bo) throws Exception {
        log.debug("SaleHandle handleSaleSave...");

        // 校验数据
        validateData(bo.getCustomerBO());

        // 保存线索
        processClue(bo);

        // 保存客户
        processCustomer(bo);

        // 保存商机
        processOpportunity(bo);

        // 保存销售单
        processSaleOrder(bo);
    }

    private void processClue(SaleBO bo) {
        Optional.ofNullable(bo.getClueBO()).ifPresent(clueBO -> {
            try {
                saveClue(clueBO);
            } catch (Exception e) {
                if (e instanceof BusinessException) {
                    throw (BusinessException) e;
                }
                throw new RuntimeException(e.getMessage());
            }
        });
    }

    private void processCustomer(SaleBO bo) {
        // if (ObjectUtil.isNotNull(bo.getCustomerBO())) {
        //     CustomerDTO customerDTO = saveCustomer(bo.getCustomerBO());
        //     bo.getOpptunityBO().setCustomerUuid(customerDTO.getUuid());
        //     bo.getOpptunityBO().setHouseId(String.valueOf(customerDTO.getHouseId()));
        //     if (ObjectUtil.isNotNull(bo.getSaleOrderBO())) {
        //         bo.getSaleOrderBO().setCustomerUuid(customerDTO.getUuid());
        //         bo.getSaleOrderBO().setHouseId(String.valueOf(customerDTO.getHouseId()));
        //     }
        // }

        Optional.ofNullable(bo.getCustomerBO()).map(customerBO -> {
                    try {
                        return saveCustomer(customerBO);
                    } catch (Exception e) {
                        log.error("{}", e);
                        if (e instanceof BusinessException) {
                            throw (BusinessException) e;
                        }
                        throw new RuntimeException(e.getMessage());
                    }
                }) // Save the customer and return CustomerDTO
                .ifPresent(customerDTO -> {
                    // Set customerUuid and houseId on OpptunityBO
                    Optional.ofNullable(bo.getOpptunityBO()).ifPresent(opptunityBO -> {
                        opptunityBO.setCustomerUuid(customerDTO.getUuid());
                        opptunityBO.setHouseId(String.valueOf(customerDTO.getHouseId()));
                    });

                    // Set customerUuid and houseId on SaleOrderBO
                    Optional.ofNullable(bo.getSaleOrderBO()).ifPresent(saleOrderBO -> {
                        saleOrderBO.setCustomerUuid(customerDTO.getUuid());
                        saleOrderBO.setHouseId(String.valueOf(customerDTO.getHouseId()));
                    });
                });
    }

    private void processSaleOrder(SaleBO bo) {
        Optional.ofNullable(bo.getSaleOrderBO()).ifPresent(saleOrderBO -> {
            try {
                saveSaleOrder(saleOrderBO);
            } catch (Exception e) {
                if (e instanceof BusinessException) {
                    throw (BusinessException) e;
                }
                throw new RuntimeException(e.getMessage());
            }
        });
    }

    private void processOpportunity(SaleBO bo) {
        Optional.ofNullable(bo.getOpptunityBO()).map(opportunityBO -> {
            try {
                return saveOpptunity(opportunityBO);
            } catch (Exception e) {
                if (e instanceof BusinessException) {
                    throw (BusinessException) e;
                }
                throw new RuntimeException(e.getMessage());
            }
        }).ifPresent(opportunity -> {
            Optional.ofNullable(bo.getSaleOrderBO())
                    .ifPresent(saleOrder -> saleOrder.setOpportunityUuid(opportunity.getUuid()));
        });
    }

    private void validateData(CustomerBO customerBO) {
        if (Optional.ofNullable(customerBO).map(CustomerBO::getIdCardNumber).filter(StrUtil::isNotEmpty).isPresent()) {

            String errMsg = "";
            String idCardNumber = customerBO.getIdCardNumber();
            String year = idCardNumber.substring(6, 10);

            if (Integer.parseInt(year) < 1900 || Integer.parseInt(year) > Calendar.getInstance().get(Calendar.YEAR)) {
                errMsg = errMsg + "身份证号码，日期（年）格式不合法， 不在1900至" + Calendar.getInstance().get(Calendar.YEAR) + "之间；";
            }

            String month = idCardNumber.substring(10, 12);
            if (Integer.parseInt(month) < 1 || Integer.parseInt(month) > 12) {
                errMsg = errMsg + "身份证号码，日期（月）格式不合法，不在1至12月之间；";
            }

            String day = idCardNumber.substring(12, 14);
            if (Integer.parseInt(day) < 1 || Integer.parseInt(day) > 31) {
                errMsg = errMsg + "身份证号码，日期（天）格式不合法；";
            }

            if (!errMsg.isEmpty()) {
                throw new BusinessException(errMsg);
            }
        }

    }

    protected void saveClue(ClueBO clueBO) throws Exception {
        log.debug("SaleHandle saveClue...");
        crmClueService.clueSave(clueBO);
    }

    private CustomerDTO saveCustomer(CustomerBO customerBO) throws Exception {
        log.debug("SaleHandle saveCustomer...");
        preHandleForCustomer(customerBO);
        CustomerDTO customerDTO = crmCustomerService.customerSave(customerBO);
        postHandleForCustomer(customerBO);
        return customerDTO;
    }

    protected void preHandleForCustomer(CustomerBO customerBO) throws Exception {
        log.debug("SaleHandle preHandleForCustomer...");
    }

    protected void postHandleForCustomer(CustomerBO customerBO) throws Exception {
        log.debug("SaleHandle postHandleForCustomer...");
    }

    protected Opportunity saveOpptunity(OpportunityBO opptunityBO) throws Exception {
        log.debug("SaleHandle saveOpptunity...");
        preHandleForOpportunity(opptunityBO);
        Opportunity opportunity = opportunityBusiness.save(opptunityBO);
        postHandleForOpportunity(opportunity, opptunityBO);
        return opportunity;
    }

    protected void preHandleForOpportunity(OpportunityBO opptunityBO) throws Exception {
        log.debug("SaleHandle preHandleForOpptunity...");
    }

    protected void postHandleForOpportunity(Opportunity opportunity, OpportunityBO opptunityBO) throws Exception {
        log.debug("SaleHandle postHandleForOpptunity...");
    }

    private void saveSaleOrder(SaleOrderBO saleOrderBO) throws Exception {
        log.debug("SaleHandle saveSaleOrder ...");
        preHandleForSaleOrder(saleOrderBO);

        saleOrderInfoService.saleOrderSave(saleOrderBO);

        postHandleForSaleOrder(saleOrderBO);
    }

    protected void preHandleForSaleOrder(SaleOrderBO saleOrderBO) throws Exception {
        log.debug("SaleHandle preHandleForSaleOrder...");
        validateDuplicateSaleOrder(saleOrderBO);
    }

    private void validateDuplicateSaleOrder(SaleOrderBO saleOrderBO) throws Exception {
        SaleOrderInfo saleOrder = saleOrderInfoService.getSaleOrderNew(saleOrderBO.getOpportunityUuid());
        if (ObjectUtil.isNotNull(saleOrder)) {
            saleOrderBO.setSaleOrderId(saleOrder.getId());
            saleOrderBO.setAddOrder(Boolean.FALSE);
            // 销售单状态是支付成功时，不能再修改状态了
            if (SaleOrderStatusEnum.PAID_SUCCESS.getKey().equals(saleOrder.getStatus())) {
                saleOrderBO.setSaleOrderStatus(SaleOrderStatusEnum.PAID_SUCCESS);
            }
        }
    }

    protected void postHandleForSaleOrder(SaleOrderBO saleOrderBO) throws Exception {
        log.debug("SaleHandle postHandleForSaleOrder...");
    }

    /**
     * 查询销售详情
     */
    protected SaleDetailDTO getSaleDetail(SaleDetailBO saleDetailBO) throws Exception {
        return null;
    }

    /**
     * 查询客户详情
     */
    protected CustomerDetailDTO getCustomerDetail(SaleDetailBO saleDetailBO) throws Exception {
        return null;
    }

    /**
     * 查询商机详情
     */
    protected OpportunityDetailDTO getOpportunityDetail(SaleDetailBO saleDetailBO) throws Exception {
        GetOpportunityDetailBO queryOpportunityDetailBO = saleDetailBO.copyOperateInfo(GetOpportunityDetailBO.class);
        queryOpportunityDetailBO.setOpportunityId(saleDetailBO.getOpportunityUuid());
        return opportunityBusiness.details(queryOpportunityDetailBO);
    }

    /**
     * 查询销售订单详情
     */
    protected SaleOrderDetailDTO getSaleOrderDetail(SaleDetailBO saleDetailBO) {
        return null;
    }

    /**
     * 处理返回值
     */
    protected SaleDetailDTO postHandle(SaleDetailDTO saleDetailDTO) {
        return null;
    }

}
